package www.authority.config.shiro;


import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import www.common.util.StringUtils;
import www.authority.config.manager.AsyncManager;
import www.authority.config.manager.factory.AsyncFactory;
import www.authority.config.token.JwtToken;
import www.authority.config.token.JwtUtil;
import www.authority.entity.SysDeptEntity;
import www.authority.entity.SysMenuEntity;
import www.authority.entity.SysRoleEntity;
import www.authority.entity.SysUserEntity;
import www.authority.service.PrivLoginService;
import www.authority.service.SysDeptService;
import www.authority.service.SysMenuService;
import www.authority.service.SysRoleService;

import java.util.*;

/**
 * @author SPPan
 */
@Component
/*@Import(ShiroManager.class)*/
public class MyRealm extends AuthorizingRealm {


    public MyRealm() {
        super(new AllowAllCredentialsMatcher());
        setAuthenticationTokenClass(JwtToken.class);

        //FIXME: 暂时禁用Cache
        setCachingEnabled(false);
    }

    @Autowired
    private PrivLoginService privLoginService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private SysDeptService sysDeptService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        SysUserEntity user = (SysUserEntity) principals.getPrimaryPrincipal();
        // 角色列表
        Set<String> roles = new HashSet<String>();
        // 功能列表
        Set<String> menus = new HashSet<String>();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            info.addRole("admin");
            info.addStringPermission("*:*:*");
        } else {
            //  用户角色
            List<SysRoleEntity> entityPerms = sysRoleService.findListByUserId(user.getUserId().intValue());
            if (StringUtils.isNotNull(entityPerms)) {
                for (SysRoleEntity perm : entityPerms) {
                    if (StringUtils.isNotNull(perm)) {
                        roles.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
                    }
                }
            }
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("userId", user.getUserId().toString());
            //  用户菜单
            List<SysMenuEntity> menuPerms = sysMenuService.findListByUserId(paramMap);
            if (StringUtils.isNotNull(menuPerms)) {
                for (SysMenuEntity perm : menuPerms) {
                    if (StringUtils.isNotNull(perm) && StringUtils.isNotEmpty(perm.getPerms())) {
                        menus.addAll(Arrays.asList(perm.getPerms().trim().split(",")));
                    }
                }
            }
            // 角色加入AuthorizationInfo认证对象
            info.setRoles(roles);
            // 权限加入AuthorizationInfo认证对象
            info.setStringPermissions(menus);
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        JwtToken upToken = (JwtToken) token;
        String tokenStr = (String) upToken.getPrincipal();
        String loginname = JwtUtil.getLoginname(tokenStr);
        String password = JwtUtil.getPassword(tokenStr);

        SysUserEntity user = null;
        try {
            user = privLoginService.login(loginname, password);
        } catch (Exception e) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginname, "1", "账号或密码不正确"));
            throw new UnknownAccountException("账号或密码不正确");
        }
        // 账号不存在
        if (user == null) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginname, "1", "账号或密码不正确"));
            throw new UnknownAccountException("账号或密码不正确");
        } else {
            // 验证token是否正确
            Boolean verify = JwtUtil.isVerify(tokenStr, user);
            if (!verify) {
                throw new RuntimeException("非法访问！");
            } else {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginname, "0", "登录成功"));
                //  用户角色
                List<SysRoleEntity> entityPerms = sysRoleService.findListByUserId(user.getUserId().intValue());
                if (StringUtils.isNotNull(entityPerms)) {
                    user.setRoles(entityPerms);
                    Long[] roles = new Long[entityPerms.size()];
                    for (int i = 0; i < entityPerms.size(); i++) {
                        roles[i] = entityPerms.get(i).getRoleId();
                    }
                    user.setRoleIds(roles);
                }
                //  用户部门
                SysDeptEntity Dept = sysDeptService.findByPrimaryKey(SysDeptEntity.class, user.getDeptId().intValue());
                if (StringUtils.isNotNull(Dept)) {
                    user.setDept(Dept);
                }
            }
        }

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());

        return info;
    }

}
